using System;
using System.Collections.Generic;
using System.Text;

//using ESBSimpleSamples.ServiceClient.ESBProcessItineraryTwoWay;
using esb = Microsoft.Practices.ESB;
using ESBSimpleSamples.ServiceClient.Enums;
using ESBSimpleSamples.ServiceClient.Helpers;

namespace ESBSimpleSamples.ServiceClient.Itineraries
{
    public class ItineraryBuilder
    {
        private List<ItineraryService> _services;

        public ItineraryBuilder()
        {
            this._services = new List<ItineraryService>();
        }

        public void AddService(ItineraryService service)
        {
            this._services.Add(service);
        }

        public void AddTransformService(string transformType)
        {
            ItineraryService mapService = new ItineraryService(ServiceName.Transform, ServiceType.Messaging);
            ResolverConnection mapResolver = new ResolverConnection(ResolverType.STATIC);
            mapResolver.TransformType = transformType;
            mapService.Resolvers.Add(mapResolver);
            this.AddService(mapService);
        }

        public void AddRoutingService(string serviceProvder, string serviceName)
        {
            ItineraryService routingService = new ItineraryService(ServiceName.Routing, ServiceType.Messaging);
            ResolverConnection routingResolver = new ResolverConnection(ResolverType.UDDI);
            //this would need to be abstracted somewhere:
            routingResolver.ServerUrl = "http://localhost/uddi";
            routingResolver.ServiceProvider = serviceProvder;
            routingResolver.ServiceName = serviceName;
            routingService.Resolvers.Add(routingResolver);
            this.AddService(routingService);
        }

        public void AddRequestResponseService()
        {
            //this will get picked up by the dynamic port from the "GlobalBank" ESB sample app:
            ItineraryService sendService = new ItineraryService("DynamicResolutionSolicitResp", ServiceType.Messaging);
            //the send has an empty resolver:
            sendService.Resolvers.Add(new ResolverConnection());
            this.AddService(sendService);
        }

        public esb.Itinerary GetItinerary()
        {
            esb.Itinerary itinerary = new esb.Itinerary();
            
            //set up service & resolver arrays:
            itinerary.Services = new esb.ItineraryServices[this._services.Count];
            itinerary.ResolverGroups = new esb.ArrayOfItineraryResolversResolvers[this._services.Count];
            
            //add services in the order they were added:
            int position = 0;
            foreach (ItineraryService service in this._services)
            {
                service.Position = position;
                itinerary.Services[position] = new esb.ItineraryServices();
                itinerary.Services[position].Service = this.GetItineraryService(service);
                //add service resolvers:                
                itinerary.ResolverGroups[position] = new esb.ArrayOfItineraryResolversResolvers();
                itinerary.ResolverGroups[position] = this.GetResolvers(service);
                position++;
            }

            //specify service instance (=first step for a new itinerary):
            itinerary.ServiceInstance = new esb.ItineraryServiceInstance();
            itinerary.ServiceInstance.name = itinerary.Services[0].Service.name;
            itinerary.ServiceInstance.type = itinerary.Services[0].Service.type;
            itinerary.ServiceInstance.state = itinerary.Services[0].Service.state;
            itinerary.ServiceInstance.position = itinerary.Services[0].Service.position;
            itinerary.ServiceInstance.isRequestResponse = itinerary.Services[0].Service.isRequestResponse;
            itinerary.ServiceInstance.isRequestResponseSpecified = itinerary.Services[0].Service.isRequestResponseSpecified;

            return itinerary;
        }

        private esb.ItineraryServicesService GetItineraryService(ItineraryService service)
        {
            esb.ItineraryServicesService esbService = new esb.ItineraryServicesService();
            esbService.name = service.ServiceName;
            esbService.type = EnumHelper.GetCode(service.Type);
            esbService.state = EnumHelper.GetCode(service.State);
            esbService.position = service.Position;
            //ES - this seems to be persistently ignored, so always set to false
            //TODO - check EB Sousrce to ee if it gets used
            esbService.isRequestResponse = false;
            esbService.isRequestResponseSpecified = true;

            return esbService;
        }

        private esb.ArrayOfItineraryResolversResolvers GetResolvers(ItineraryService service)
        {
            esb.ArrayOfItineraryResolversResolvers resolvers = new esb.ArrayOfItineraryResolversResolvers();
            resolvers.serviceId = string.Format("{0}{1}", service.ServiceName, service.Position);
            //build up the resolvers - wrap each connection string in CDATA tags and build into one string:
            StringBuilder resolverBuilder = new StringBuilder();
            foreach (ResolverConnection resolver in service.Resolvers)
            {
                resolverBuilder.AppendFormat(@"<![CDATA[{0}]]>", resolver.GetConnectionString());
            }
            resolvers.Value = resolverBuilder.ToString();

            return resolvers;
        }
    }
}
